﻿using MiniFox.Components;
using MiniFox.Configurations;
using MiniFox.Data.Configurations;
using MiniFox.Data.Mapping;
using MiniFox.Data.NativeClient;
using MiniFox.Resources;
using MiniFox.Utility;
using System.Data;
using System.Data.Common;
using System.Reflection;

namespace MiniFox.Data
{
    /// <summary>
    /// 为数据库连接以及执行语句提供方法
    /// </summary>
    public abstract class Database : Component
    {
        private int _cmdTimeOut;
        private string _providerName;
        private string _connectionString;
        private bool _raiseException;

        private DbConnectionStringBuilder _connectionStringBuilder;
        private DbProviderFactory _dbFactory;
        /// <summary>
        /// 发生异常时引发的事件
        /// </summary>
        public event DbExceptionEventHandler _exceptionEventHandler;

        #region 静态成员
        /// <summary>
        /// 
        /// </summary>
        public static DatabaseConfiguration Configuration
        {
            get
            {
                return ConfigurationFactory.GetConfig<DatabaseConfiguration>();
            }
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="connectionName"></param>
        /// <returns></returns>
        public static Database CreateDatabase(string connectionName)
        {
            var connectionConfig = Configuration.Connections[connectionName];
            return CreateDatabase(connectionConfig.ConnectionString, connectionConfig.ProviderName);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="connectionString"></param>
        /// <param name="providerName"></param>
        /// <returns></returns>
        public static Database CreateDatabase(string connectionString, string providerName)
        {
            var providerSetting = Configuration.ProviderSettings[providerName];
            var basetype = typeof(Database);
            if (string.IsNullOrWhiteSpace(providerSetting.TypeName))
            {
                throw new InvalidCastException(string.Format(CommonMessages.MSG_CommonTypeUnmatched, providerSetting.Name, basetype.FullName));
            }
            Type type = providerSetting;
            if (!basetype.IsAssignableFrom(type))
                throw new InvalidCastException(string.Format(CommonMessages.MSG_CommonTypeUnmatched, providerSetting.Name, basetype.FullName));
            var database = Activator.CreateInstance(type, connectionString, providerName) as Database;

            return database;
        }
        #endregion

        #region 构造
        /// <summary>
        /// 
        /// </summary>
        /// <param name="connectionName"></param>
        protected Database(string connectionName) : this(Configuration.Connections[connectionName])
        {

        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="connectionConfig"></param>
        protected Database(ConnectionConfiguration connectionConfig) : this(connectionConfig.ConnectionString, connectionConfig.ProviderName)
        {
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="connectionString">数据库连接字符串</param>
        /// <param name="providerName">数据提供程序名</param>
        protected Database(string connectionString, string providerName)
        {
            if (string.IsNullOrEmpty(connectionString) || string.IsNullOrEmpty(providerName))
            {
                throw new DataException();
            }
            this._cmdTimeOut = 10;
            this._connectionString = connectionString;
            this._providerName = providerName;
            this._raiseException = false;

            this.RegisterFactory();
        }

        #endregion

        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        protected void RegisterFactory()
        {
            var names = DbProviderFactories.GetProviderInvariantNames();
            if (names.Contains(this.ProviderName))
            {
                return;
            }
            var factory = CreateDbProviderFactory();
            DbProviderFactories.RegisterFactory(this.ProviderName, factory);
        }
        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        protected abstract DbProviderFactory CreateDbProviderFactory();

        #region 属性
        /// <summary>
        /// 获取或设置数据库操作执行超时时限(单位:秒),默认30秒
        /// </summary>
        public int ExecuteTimeout
        {
            get { return _cmdTimeOut; }
            set { _cmdTimeOut = value; }
        }
        /// <summary>
        /// 获取或设置数据库操作异常时是否抛出
        /// </summary>
        public bool RaiseException
        {
            get { return _raiseException; }
            set { _raiseException = value; }
        }
        /// <summary>
        /// 获取当前连接字符串
        /// </summary>
        protected internal string ConnectionString
        {
            get
            {
                return _connectionString;
            }
        }
        /// <summary>
        /// 获取数据提供程序名
        /// </summary>
        public string ProviderName
        {
            get
            {
                if (string.IsNullOrEmpty(_providerName))
                {
                    throw new DataException();
                }
                return _providerName;
            }
        }
        /// <summary>
        /// 参数前缀
        /// </summary>
        public abstract string ParameterPrefix
        {
            get;
        }
        /// <summary>
        /// 获取数据库连接工厂
        /// </summary>
        public DbProviderFactory DataProviderFactory
        {
            get
            {
                if (this._dbFactory == null)
                {
                    this._dbFactory = DbProviderFactories.GetFactory(this.ProviderName);
                }
                return this._dbFactory;
            }
        }
        /// <summary>
        /// 获取数据库连接字符串生成器
        /// </summary>
        public DbConnectionStringBuilder ConnectionStringBuilder
        {
            get
            {
                if (this._connectionStringBuilder == null)
                {
                    this._connectionStringBuilder = this.DataProviderFactory.CreateConnectionStringBuilder();
                    this._connectionStringBuilder.ConnectionString = this.ConnectionString;
                }
                return _connectionStringBuilder;
            }
        }

        #endregion

        #region 检查连接状态
        /// <summary>
        /// 
        /// </summary>
        public virtual void TestConnection()
        {
            var conn = this.CreateConnection();
            try
            {
                conn.Open();
                conn.Close();
            }
            catch (Exception e)
            {
                this.OnExceptionEventRaise(ConnectionString, null, e);
            }
            finally
            {
                conn.Dispose();
            }
        }

        /// <summary>
        /// 获取指定连接对象的状态
        /// </summary>
        /// <param name="con">指定连接对象</param>
        /// <returns>状态枚举</returns>
        public static ConnectionState GetConnectionState(DbConnection con)
        {
            return con.State;
        }
        #endregion

        #region 创建数据访问对象
        /// <summary>
        /// 创建连接对象
        /// </summary>
        /// <returns></returns>
        public DbConnection CreateConnection()
        {
            DbConnection connection = this.DataProviderFactory.CreateConnection();
            connection.ConnectionString = this.ConnectionString;

            return connection;
        }

        #region 创建命令对象
        /// <summary>
        /// 创建命令对象
        /// </summary>
        /// <param name="sqlCommandTxt">创建命令对象所需的sql语句</param>
        /// <param name="parameters">命令参数(可变)</param>
        /// <returns>返回生成的命令对象</returns>
        public DbCommand CreateCommand(string sqlCommandTxt, params DbParameter[] parameters)
        {
            return CreateCommand(sqlCommandTxt, CommandType.Text, parameters);
        }
        /// <summary>
        /// 创建命令对象
        /// </summary>
        /// <param name="sqlCommandTxt">创建命令对象所需的sql语句</param>
        /// <param name="cmdType">指定该命令将被解析为一般的sql语句还是存储过程名</param>
        /// <param name="parameters">命令参数(可变)</param>
        /// <returns></returns>
        public virtual DbCommand CreateCommand(string sqlCommandTxt, CommandType cmdType, params DbParameter[] parameters)
        {
            DbConnection connection = CreateConnection();
            DbCommand command = connection.CreateCommand();
            command.CommandText = sqlCommandTxt;
            if (parameters != null && parameters.Length > 0)
            {
                command.Parameters.AddRange(parameters);
            }
            command.CommandType = cmdType;
            command.CommandTimeout = this.ExecuteTimeout;
            return command;
        }
        /// <summary>
        /// 创建命令对象
        /// </summary>
        /// <param name="sqlCommandTxt">创建命令对象所需的sql语句</param>
        /// <param name="cmdType">指定该命令将被解析为一般的sql语句还是存储过程名</param>
        /// <param name="parameters">命令参数字典</param>
        /// <returns></returns>
        public DbCommand CreateCommand(string sqlCommandTxt, CommandType cmdType, IDictionary<string, object> parameters)
        {
            if (parameters == null || parameters.Count <= 0)
            {
                return this.CreateCommand(sqlCommandTxt, cmdType);
            }

            var parArray = new DbParameter[parameters.Count];
            int i = 0;
            foreach (var parameter in parameters)
            {
                parArray[i++] = this.CreateParameter(parameter.Key, parameter.Value);
            }
            return this.CreateCommand(sqlCommandTxt, cmdType, parArray);
        }
        #endregion

        #region 创建 data adapter
        /// <summary>
        /// 创建数据库适配器
        /// </summary>
        /// <param name="selectCommandTxt"></param>
        /// <param name="parameters"></param>
        /// <returns></returns>
        public DbDataAdapter CreateDataAdapter(string selectCommandTxt, params DbParameter[] parameters)
        {
            return CreateDataAdapter(selectCommandTxt, CommandType.Text, parameters);
        }
        /// <summary>
        /// 创建数据库适配器
        /// </summary>
        /// <param name="selectCommandTxt"></param>
        /// <param name="cmdType"></param>
        /// <param name="parameters"></param>
        /// <returns></returns>
        public DbDataAdapter CreateDataAdapter(string selectCommandTxt, CommandType cmdType, params DbParameter[] parameters)
        {
            DbCommand selectcommand = CreateCommand(selectCommandTxt, cmdType, parameters);
            return CreateDataAdapter(selectcommand);
        }
        /// <summary>
        /// 创建数据库适配器
        /// </summary>
        /// <param name="selectcommand"></param>
        /// <returns></returns>
        protected internal virtual DbDataAdapter CreateDataAdapter(DbCommand selectcommand)
        {
            DbDataAdapter adapter = DataProviderFactory.CreateDataAdapter();
            adapter.SelectCommand = selectcommand;
            return adapter;
        }
        #endregion

        #region 创建参数
        /// <summary>
        /// 
        /// </summary>
        /// <param name="parameterName"></param>
        /// <param name="val"></param>
        /// <returns></returns>
        public DbParameter CreateParameter(string parameterName, object val)
        {
            return CreateParameter(parameterName, val, ParameterDirection.Input);
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="parameterName"></param>
        /// <param name="val"></param>
        /// <param name="direction"></param>
        /// <returns></returns>
        public DbParameter CreateParameter(string parameterName, object val, ParameterDirection direction)
        {
            DbParameter par = CreateParameter(parameterName, string.Empty, val.GetType(), direction);
            par.Value = val;
            return par;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="parameterName"></param>
        /// <param name="srcName"></param>
        /// <param name="type"></param>
        /// <param name="direction"></param>
        /// <returns></returns>
        public virtual DbParameter CreateParameter(string parameterName, string srcName, Type type, ParameterDirection direction)
        {
            DbParameter par = DataProviderFactory.CreateParameter();
            par.ParameterName = parameterName;
            par.SourceColumn = srcName;
            par.Direction = direction;
            SetParameterDbType(par, type);
            par.ParameterName = string.IsNullOrWhiteSpace(parameterName) ? $"{ParameterPrefix}{srcName}" : parameterName;
            if (!par.ParameterName.StartsWith(ParameterPrefix))
            {
                par.ParameterName = $"{ParameterPrefix}{par.ParameterName}";
            }
            return par;
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="dbParameter"></param>
        /// <param name="type"></param>
        protected abstract void SetParameterDbType(DbParameter dbParameter, Type type);

        #endregion
        /// <summary>
        /// 创建命令生成器
        /// </summary>
        /// <returns></returns>
        public DbCommandBuilder CreateCommandBuilder()
        {
            return DataProviderFactory.CreateCommandBuilder();
        }

        #endregion

        #region ExecuteNonQuery

        #region 异步
        /// <summary>
        /// 执行协参SQL操作语句
        /// </summary>
        /// <param name="sqlCommandTxt">SQL语句</param>
        /// <param name="parameters">参数对象集合</param>
        /// <returns>是否执行成功</returns>
        public Task<int> ExecuteNonQueryAsync(string sqlCommandTxt, params DbParameter[] parameters)
        {
            return ExecuteNonQueryAsync(sqlCommandTxt, CommandType.Text, parameters);
        }

        /// <summary>
        /// 执行协参SQL操作语句
        /// </summary>
        /// <param name="sqlCommandTxt">SQL语句</param>
        /// <param name="cmdType">命令类型</param>
        /// <param name="parameters">参数对象集合</param>
        /// <returns>是否执行成功</returns>
        public async Task<int> ExecuteNonQueryAsync(string sqlCommandTxt, CommandType cmdType, params DbParameter[] parameters)
        {
            await using (DbCommand command = this.CreateCommand(sqlCommandTxt, cmdType, parameters))
            {
                try
                {
                    return await ExecuteNonQueryAsync(command);
                }
                finally
                {
                    await command.Connection.CloseAsync();
                    await command.Connection.DisposeAsync();
                }
            }
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="command"></param>
        /// <returns></returns>
        protected internal async virtual Task<int> ExecuteNonQueryAsync(DbCommand command)
        {
            int rowCount = 0;

            try
            {
                if (GetConnectionState(command.Connection) != ConnectionState.Open)
                    await command.Connection.OpenAsync();
                rowCount = await command.ExecuteNonQueryAsync();
            }
            catch (Exception e)
            {
                OnExceptionEventRaise(command.Connection.Database, command.CommandText, e);
            }

            return rowCount;
        }
        #endregion

        #region 同步
        /// <summary>
        /// 执行协参SQL操作语句
        /// </summary>
        /// <param name="sqlCommandTxt">SQL语句</param>
        /// <param name="parameters">参数对象集合</param>
        /// <returns>是否执行成功</returns>
        public int ExecuteNonQuery(string sqlCommandTxt, params DbParameter[] parameters)
        {
            return ExecuteNonQuery(sqlCommandTxt, CommandType.Text, parameters);
        }

        /// <summary>
        /// 执行协参SQL操作语句
        /// </summary>
        /// <param name="sqlCommandTxt">SQL语句</param>
        /// <param name="cmdType">命令类型</param>
        /// <param name="parameters">参数对象集合</param>
        /// <returns>是否执行成功</returns>
        public int ExecuteNonQuery(string sqlCommandTxt, CommandType cmdType, params DbParameter[] parameters)
        {
            using (DbCommand command = CreateCommand(sqlCommandTxt, cmdType, parameters))
            {
                try
                {
                    return ExecuteNonQuery(command);
                }
                finally
                {
                    command.Connection.Close();
                    command.Connection.Dispose();
                }
            }
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="command"></param>
        /// <returns></returns>
        protected internal virtual int ExecuteNonQuery(DbCommand command)
        {
            int rowCount = 0;

            try
            {
                if (GetConnectionState(command.Connection) != ConnectionState.Open)
                    command.Connection.Open();
                rowCount = command.ExecuteNonQuery();
            }
            catch (Exception e)
            {
                OnExceptionEventRaise(command.Connection.Database, command.CommandText, e);
            }

            return rowCount;
        }
        #endregion

        #endregion

        #region ExecuteScaler

        #region 异步
        /// <summary>
        /// 
        /// </summary>
        /// <param name="sqlCommandTxt"></param>
        /// <param name="parameters"></param>
        /// <returns></returns>
        public Task<T> ExecuteScalerAsync<T>(string sqlCommandTxt, params DbParameter[] parameters)
        {
            return ExecuteScalerAsync<T>(sqlCommandTxt, CommandType.Text, parameters);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sqlCommandTxt"></param>
        /// <param name="cmdType"></param>
        /// <param name="parameters"></param>
        /// <returns></returns>
        public async Task<T> ExecuteScalerAsync<T>(string sqlCommandTxt, CommandType cmdType, params DbParameter[] parameters)
        {
            await using (DbCommand command = CreateCommand(sqlCommandTxt, cmdType, parameters))
            {
                try
                {
                    return await ExecuteScalerAsync<T>(command);
                }
                finally
                {
                    await command.Connection.CloseAsync();
                    await command.Connection.DisposeAsync();
                }
            }
        }
        /// <summary>
        /// 
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="command"></param>
        /// <returns></returns>
        protected internal async virtual Task<T> ExecuteScalerAsync<T>(DbCommand command)
        {
            T result = default;

            try
            {
                if (GetConnectionState(command.Connection) != ConnectionState.Open)
                    await command.Connection.OpenAsync();
                var obj = await command.ExecuteScalarAsync();
                result = (T)obj;
            }
            catch (Exception e)
            {
                OnExceptionEventRaise(command.Connection.Database, command.CommandText, e);
            }

            return result;
        }
        #endregion

        #region 同步
        /// <summary>
        /// 
        /// </summary>
        /// <param name="sqlCommandTxt"></param>
        /// <param name="parameters"></param>
        /// <returns></returns>
        public T ExecuteScaler<T>(string sqlCommandTxt, params DbParameter[] parameters)
        {
            return ExecuteScaler<T>(sqlCommandTxt, CommandType.Text, parameters);
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="sqlCommandTxt"></param>
        /// <param name="cmdType"></param>
        /// <param name="parameters"></param>
        /// <returns></returns>
        public virtual T ExecuteScaler<T>(string sqlCommandTxt, CommandType cmdType, params DbParameter[] parameters)
        {
            using (DbCommand command = CreateCommand(sqlCommandTxt, cmdType, parameters))
            {
                try
                {
                    return ExecuteScaler<T>(command);
                }
                finally
                {
                    command.Connection.Close();
                    command.Connection.Dispose();
                }
            }
        }
        /// <summary>
        /// 
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="command"></param>
        /// <returns></returns>
        protected internal virtual T ExecuteScaler<T>(DbCommand command)
        {
            T result = default;

            try
            {
                if (GetConnectionState(command.Connection) != ConnectionState.Open)
                    command.Connection.Open();
                result = (T)command.ExecuteScalar();
            }
            catch (Exception e)
            {
                OnExceptionEventRaise(command.Connection.Database, command.CommandText, e);
            }

            return result;
        }
        #endregion

        #endregion

        #region ExecuteReader

        #region 列表数据

        #region 填充集合

        #region 异步
        /// <summary>
        /// 通过指定查询语句获取数据
        /// </summary>
        /// <param name="dataList">要填充的列表</param>
        /// <param name="sqlCommandTxt">要执行的查询语句</param>
        /// <param name="parameters">查询语句中的参数</param>
        /// <returns></returns>
        public Task<int> ExecuteReaderAsync<T>(ICollection<T> dataList, string sqlCommandTxt, params DbParameter[] parameters)
        {
            return ExecuteReaderAsync(dataList, sqlCommandTxt, CommandType.Text, parameters);
        }

        /// <summary>
        /// 通过指定查询语句获取数据
        /// </summary>
        /// <param name="dataList">要填充的列表</param>
        /// <param name="sqlCommandTxt">要执行的查询语句</param>
        /// <param name="cmdType">查询语句的类型，一般语句或者存储过程</param>
        /// <param name="parameters">查询语句中的参数</param>
        /// <returns></returns>
        public Task<int> ExecuteReaderAsync<T>(ICollection<T> dataList, string sqlCommandTxt, CommandType cmdType, params DbParameter[] parameters)
        {
            return ExecuteReaderAsync(dataList, sqlCommandTxt, cmdType, 0, parameters);
        }
        /// <summary>
        /// 通过指定查询语句获取数据
        /// </summary>
        /// <param name="dataList">要填充的列表</param>
        /// <param name="sqlCommandTxt">要执行的查询语句</param>
        /// <param name="cmdType">查询语句的类型，一般语句或者存储过程</param>
        /// <param name="maxRowCount"></param>
        /// <param name="parameters">查询语句中的参数</param>
        /// <returns></returns>
        public async Task<int> ExecuteReaderAsync<T>(ICollection<T> dataList, string sqlCommandTxt, CommandType cmdType, int maxRowCount, params DbParameter[] parameters)
        {
            using (DbCommand command = CreateCommand(sqlCommandTxt, cmdType, parameters))
            {
                try
                {
                    return await ExecuteReaderAsync(dataList, command, maxRowCount, CommandBehavior.CloseConnection);
                }
                finally
                {
                    command.Connection.Close();
                    command.Connection.Dispose();
                }
            }
        }
        /// <summary>
        /// 
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="dataList"></param>
        /// <param name="command"></param>
        /// <param name="maxRowCount"></param>
        /// <param name="commandBehavior"></param>
        /// <returns></returns>
        protected internal async virtual Task<int> ExecuteReaderAsync<T>(ICollection<T> dataList, DbCommand command, int maxRowCount, CommandBehavior commandBehavior)
        {
            int rowCount = 0;

            try
            {
                if (GetConnectionState(command.Connection) != ConnectionState.Open)
                    command.Connection.Open();
                await using (DbDataReader reader = await command.ExecuteReaderAsync(commandBehavior))
                {
                    if (reader.HasRows)
                    {
                        dataList.Clear();
                        while (await reader.ReadAsync())
                        {
                            T entity = await LoadObjectAsync<T>(reader);

                            dataList.Add(entity);
                            rowCount += 1;
                            if (maxRowCount > 0 && rowCount >= maxRowCount)
                            {
                                break;
                            }
                        }
                    }
                    await reader.CloseAsync();
                }
            }
            catch (Exception e)
            {
                OnExceptionEventRaise(ConnectionString, command.CommandText, e);
            }
            return rowCount;
        }

        #endregion

        #region 同步
        /// <summary>
        /// 通过指定查询语句获取数据
        /// </summary>
        /// <param name="dataList">要填充的列表</param>
        /// <param name="sqlCommandTxt">要执行的查询语句</param>
        /// <param name="parameters">查询语句中的参数</param>
        /// <returns></returns>
        public int ExecuteReader<T>(ICollection<T> dataList, string sqlCommandTxt, params DbParameter[] parameters)
        {
            return ExecuteReader(dataList, sqlCommandTxt, CommandType.Text, parameters);
        }
        /// <summary>
        /// 通过指定查询语句获取数据
        /// </summary>
        /// <param name="dataList">要填充的列表</param>
        /// <param name="sqlCommandTxt">要执行的查询语句</param>
        /// <param name="cmdType">查询语句的类型，一般语句或者存储过程</param>
        /// <param name="parameters">查询语句中的参数</param>
        /// <returns></returns>
        public int ExecuteReader<T>(ICollection<T> dataList, string sqlCommandTxt, CommandType cmdType, params DbParameter[] parameters)
        {
            return ExecuteReader(dataList, sqlCommandTxt, cmdType, 0, parameters);
        }
        /// <summary>
        /// 通过指定查询语句获取数据
        /// </summary>
        /// <param name="dataList">要填充的列表</param>
        /// <param name="sqlCommandTxt">要执行的查询语句</param>
        /// <param name="cmdType">查询语句的类型，一般语句或者存储过程</param>
        /// <param name="maxRowCount"></param>
        /// <param name="parameters">查询语句中的参数</param>
        /// <returns></returns>
        public int ExecuteReader<T>(ICollection<T> dataList, string sqlCommandTxt, CommandType cmdType, int maxRowCount, params DbParameter[] parameters)
        {
            using (DbCommand command = CreateCommand(sqlCommandTxt, cmdType, parameters))
            {
                try
                {
                    return ExecuteReader(dataList, command, maxRowCount, CommandBehavior.CloseConnection);
                }
                finally
                {
                    command.Connection.Close();
                    command.Connection.Dispose();
                }
            }
        }
        /// <summary>
        /// 
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="dataList"></param>
        /// <param name="command"></param>
        /// <param name="maxRowCount"></param>
        /// <param name="commandBehavior"></param>
        /// <returns></returns>
        protected internal virtual int ExecuteReader<T>(ICollection<T> dataList, DbCommand command, int maxRowCount, CommandBehavior commandBehavior)
        {
            int rowCount = 0;
            try
            {
                if (GetConnectionState(command.Connection) != ConnectionState.Open)
                    command.Connection.Open();
                using (DbDataReader reader = command.ExecuteReader(commandBehavior))
                {
                    if (reader.HasRows)
                    {
                        dataList.Clear();
                        while (reader.Read())
                        {
                            T entity = LoadObject<T>(reader);

                            dataList.Add(entity);
                            rowCount += 1;
                            if (maxRowCount > 0 && rowCount >= maxRowCount)
                            {
                                break;
                            }
                        }
                    }
                    reader.Close();
                }
            }
            catch (Exception e)
            {
                OnExceptionEventRaise(ConnectionString, command.CommandText, e);
            }
            return rowCount;
        }
        #endregion

        #endregion

        #region 返回字典集列表(此处返回使用IList<T>接口的理由：ICollection<T>接口没有this[int index]索引，将导致返回对象无法直接使用for循环遍历而增加编码复杂度)

        #region 异步
        /// <summary>
        /// 
        /// </summary>
        /// <param name="sqlCommandTxt"></param>
        /// <param name="parameters"></param>
        /// <returns></returns>
        public Task<IList<IDictionary<string, object>>> ExecuteReaderAsync(string sqlCommandTxt, params DbParameter[] parameters)
        {
            return ExecuteReaderAsync(sqlCommandTxt, CommandType.Text, 0, parameters);
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="sqlCommandTxt"></param>
        /// <param name="cmdType"></param>
        /// <param name="parameters"></param>
        /// <returns></returns>
        public Task<IList<IDictionary<string, object>>> ExecuteReaderAsync(string sqlCommandTxt, CommandType cmdType, params DbParameter[] parameters)
        {
            return ExecuteReaderAsync(sqlCommandTxt, cmdType, 0, parameters);
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="sqlCommandTxt"></param>
        /// <param name="cmdType"></param>
        /// <param name="maxRowCount"></param>
        /// <param name="parameters"></param>
        /// <returns></returns>
        public async Task<IList<IDictionary<string, object>>> ExecuteReaderAsync(string sqlCommandTxt, CommandType cmdType, int maxRowCount, params DbParameter[] parameters)
        {
            await using (DbCommand command = CreateCommand(sqlCommandTxt, cmdType, parameters))
            {
                try
                {
                    var dataList = await ExecuteReaderAsync(command, maxRowCount, CommandBehavior.CloseConnection);
                    return dataList;
                }
                finally
                {
                    await command.Connection.CloseAsync();
                    await command.Connection.DisposeAsync();
                }
            }
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="command"></param>
        /// <param name="maxRowCount"></param>
        /// <param name="commandBehavior"></param>
        /// <returns></returns>
        protected internal async virtual Task<IList<IDictionary<string, object>>> ExecuteReaderAsync(DbCommand command, int maxRowCount, CommandBehavior commandBehavior)
        {
            IList<IDictionary<string, object>> dataList = new List<IDictionary<string, object>>();

            int rowCount = 0;
            try
            {
                if (GetConnectionState(command.Connection) != ConnectionState.Open)
                    await command.Connection.OpenAsync();
                await using (DbDataReader reader = await command.ExecuteReaderAsync(commandBehavior))
                {
                    if (reader.HasRows)
                    {
                        while (await reader.ReadAsync())
                        {
                            dataList.Add(LoadDataReader(reader));
                            rowCount++;
                            if (maxRowCount > 0 && rowCount >= maxRowCount)
                            {
                                break;
                            }
                        }
                    }
                    await reader.CloseAsync();
                }
            }
            catch (Exception e)
            {
                OnExceptionEventRaise(ConnectionString, command.CommandText, e);
            }
            return dataList;
        }
        #endregion

        #region 同步
        /// <summary>
        /// 
        /// </summary>
        /// <param name="sqlCommandTxt"></param>
        /// <param name="parameters"></param>
        /// <returns></returns>
        public IList<IDictionary<string, object>> ExecuteReader(string sqlCommandTxt, params DbParameter[] parameters)
        {
            return ExecuteReader(sqlCommandTxt, CommandType.Text, 0, parameters);
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="sqlCommandTxt"></param>
        /// <param name="cmdType"></param>
        /// <param name="parameters"></param>
        /// <returns></returns>
        public IList<IDictionary<string, object>> ExecuteReader(string sqlCommandTxt, CommandType cmdType, params DbParameter[] parameters)
        {
            return ExecuteReader(sqlCommandTxt, cmdType, 0, parameters);
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="sqlCommandTxt"></param>
        /// <param name="cmdType"></param>
        /// <param name="maxRowCount"></param>
        /// <param name="parameters"></param>
        /// <returns></returns>
        public IList<IDictionary<string, object>> ExecuteReader(string sqlCommandTxt, CommandType cmdType, int maxRowCount, params DbParameter[] parameters)
        {
            using (DbCommand command = CreateCommand(sqlCommandTxt, cmdType, parameters))
            {
                try
                {
                    var dataList = ExecuteReader(command, maxRowCount, CommandBehavior.CloseConnection);
                    return dataList;
                }
                finally
                {
                    command.Connection.Close();
                    command.Connection.Dispose();
                }
            }
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="command"></param>
        /// <param name="maxRowCount"></param>
        /// <param name="commandBehavior"></param>
        /// <returns></returns>
        protected internal virtual IList<IDictionary<string, object>> ExecuteReader(DbCommand command, int maxRowCount, CommandBehavior commandBehavior)
        {
            IList<IDictionary<string, object>> dataList = new List<IDictionary<string, object>>();

            int rowCount = 0;
            try
            {
                if (GetConnectionState(command.Connection) != ConnectionState.Open)
                    command.Connection.Open();
                using (DbDataReader reader = command.ExecuteReader(commandBehavior))
                {
                    if (reader.HasRows)
                    {
                        while (reader.Read())
                        {
                            dataList.Add(LoadDataReader(reader));
                            rowCount += 1;
                            if (maxRowCount > 0 && rowCount >= maxRowCount)
                            {
                                break;
                            }
                        }
                    }
                    reader.Close();
                }
            }
            catch (Exception e)
            {
                OnExceptionEventRaise(ConnectionString, command.CommandText, e);
            }
            return dataList;
        }
        #endregion

        #endregion

        #endregion

        #region 单条记录

        #region 异步
        /// <summary>
        /// 
        /// </summary>
        /// <param name="sqlCommandTxt"></param>
        /// <param name="cmdType"></param>
        /// <param name="parameters"></param>
        /// <returns></returns>
        public async Task<IDictionary<string, object>> LoadObjectAsync(string sqlCommandTxt, CommandType cmdType, params DbParameter[] parameters)
        {
            await using (DbCommand command = CreateCommand(sqlCommandTxt, cmdType, parameters))
            {
                try
                {
                    return await LoadObjectAsync(command);
                }
                finally
                {
                    await command.Connection.CloseAsync();
                    await command.Connection.DisposeAsync();
                }
            }
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="command"></param>
        /// <returns></returns>
        protected internal async virtual Task<IDictionary<string, object>> LoadObjectAsync(DbCommand command)
        {
            IDictionary<string, object> result = null;
            try
            {
                if (GetConnectionState(command.Connection) != ConnectionState.Open)
                    await command.Connection.OpenAsync();
                await using (DbDataReader reader = await command.ExecuteReaderAsync(CommandBehavior.SingleRow))
                {
                    if (reader.HasRows && await reader.ReadAsync())
                    {
                        result = LoadDataReader(reader);
                    }
                    await reader.CloseAsync();
                }
            }
            catch (Exception e)
            {
                OnExceptionEventRaise(ConnectionString, command.CommandText, e);
            }
            return result;
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="sqlCommandTxt"></param>
        /// <param name="cmdType"></param>
        /// <param name="parameters"></param>
        /// <returns></returns>
        public async Task<T> LoadObjectAsync<T>(string sqlCommandTxt, CommandType cmdType, params DbParameter[] parameters) where T : class
        {
            await using (DbCommand command = CreateCommand(sqlCommandTxt, cmdType, parameters))
            {
                try
                {
                    return await LoadObjectAsync<T>(command);
                }
                finally
                {
                    await command.Connection.CloseAsync();
                    await command.Connection.DisposeAsync();
                }
            }
        }
        /// <summary>
        /// 
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="command"></param>
        /// <returns></returns>
        protected internal async virtual Task<T> LoadObjectAsync<T>(DbCommand command) where T : class
        {
            T result = null;
            try
            {
                if (GetConnectionState(command.Connection) != ConnectionState.Open)
                    await command.Connection.OpenAsync();

                await using (DbDataReader reader = await command.ExecuteReaderAsync(CommandBehavior.SingleRow))
                {
                    if (reader.HasRows && await reader.ReadAsync())
                    {
                        result = LoadObject<T>(reader);
                    }
                    await reader.CloseAsync();
                }
            }
            catch (Exception e)
            {
                OnExceptionEventRaise(ConnectionString, command.CommandText, e);
            }
            return result;
        }
        #endregion

        #region 同步
        /// <summary>
        /// 
        /// </summary>
        /// <param name="sqlCommandTxt"></param>
        /// <param name="cmdType"></param>
        /// <param name="parameters"></param>
        /// <returns></returns>
        public virtual IDictionary<string, object> LoadObject(string sqlCommandTxt, CommandType cmdType, params DbParameter[] parameters)
        {
            using (DbCommand command = CreateCommand(sqlCommandTxt, cmdType, parameters))
            {
                try
                {
                    return LoadObject(command);
                }
                finally
                {
                    command.Connection.Close();
                    command.Connection.Dispose();
                }
            }
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="command"></param>
        /// <returns></returns>
        protected internal virtual IDictionary<string, object> LoadObject(DbCommand command)
        {
            IDictionary<string, object> result = null;

            try
            {
                if (GetConnectionState(command.Connection) != ConnectionState.Open)
                    command.Connection.Open();
                using (DbDataReader reader = command.ExecuteReader(CommandBehavior.SingleRow))
                {
                    if (reader.HasRows && reader.Read())
                    {
                        result = LoadDataReader(reader);
                    }
                    reader.Close();
                }
            }
            catch (Exception e)
            {
                OnExceptionEventRaise(ConnectionString, command.CommandText, e);
            }
            return result;
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="sqlCommandTxt"></param>
        /// <param name="cmdType"></param>
        /// <param name="parameters"></param>
        /// <returns></returns>
        public T LoadObject<T>(string sqlCommandTxt, CommandType cmdType, params DbParameter[] parameters) where T : class
        {
            using (DbCommand command = CreateCommand(sqlCommandTxt, cmdType, parameters))
            {
                try
                {
                    return LoadObject<T>(command);
                }
                finally
                {
                    command.Connection.Close();
                    command.Connection.Dispose();
                }
            }
        }
        /// <summary>
        /// 
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="command"></param>
        /// <returns></returns>
        protected internal virtual T LoadObject<T>(DbCommand command) where T : class
        {
            T result = null;
            try
            {
                if (GetConnectionState(command.Connection) != ConnectionState.Open)
                    command.Connection.Open();

                using (DbDataReader reader = command.ExecuteReader(CommandBehavior.SingleRow))
                {
                    if (reader.HasRows && reader.Read())
                    {
                        result = LoadObject<T>(reader);
                    }
                    reader.Close();
                }
            }
            catch (Exception e)
            {
                OnExceptionEventRaise(ConnectionString, command.CommandText, e);
            }
            return result;
        }
        #endregion

        #endregion

        #region 异步读取
        /// <summary>
        /// 
        /// </summary>
        /// <param name="reader"></param>
        /// <param name="i"></param>
        /// <returns></returns>
        protected virtual Task<object> GetValueAsync(DbDataReader reader, int i)
        {
            return reader.GetFieldValueAsync<object>(i);
        }
        /// <summary>
        /// 
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="reader"></param>
        /// <returns></returns>
        protected internal async virtual Task<T> LoadObjectAsync<T>(DbDataReader reader)
        {
            Type type = typeof(T);
            T entity = Activator.CreateInstance<T>();
            ITableMapping tableMapping = TableMapping.GetTableMapping<T>();

            foreach (IColumnMapping colMapping in tableMapping.ColumnMappings)
            {
                int i = reader.GetOrdinal(colMapping.SourceColumn);
                if (i < 0)
                    continue;

                object val = await GetValueAsync(reader, i);
                if (val == DBNull.Value || val == null)
                    continue;
                string fieldName = colMapping.DataSetColumn;
                PropertyInfo property = type.GetProperty(fieldName);

                if (property.PropertyType.IsEnum)
                {
                    val = Enum.ToObject(property.PropertyType, val); ;
                }
                property.SetValue(entity, val);
            }
            return entity;
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="reader"></param>
        /// <returns></returns>
        protected internal async virtual Task<IDictionary<string, object>> LoadDataReaderAsync(DbDataReader reader)
        {
            IDictionary<string, object> row = new Dictionary<string, object>(StringComparer.OrdinalIgnoreCase);
            for (int i = 0; i < reader.FieldCount; i++)
            {
                string fieldName = reader.GetName(i);
                object val;
                if (!reader.IsDBNull(i))
                    val = await reader.GetFieldValueAsync<object>(i);
                else
                    val = null;

                row.Add(fieldName, val);
            }
            return row;
        }
        #endregion

        #region 同步读取
        /// <summary>
        /// 
        /// </summary>
        /// <param name="reader"></param>
        /// <param name="i"></param>
        /// <returns></returns>
        protected virtual object GetValue(DbDataReader reader, int i)
        {
            object val = reader.GetValue(i);
            return val;
        }
        /// <summary>
        /// 
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="reader"></param>
        /// <returns></returns>
        protected internal virtual T LoadObject<T>(DbDataReader reader)
        {
            Type type = typeof(T);
            T entity = Activator.CreateInstance<T>();
            ITableMapping tableMapping = TableMapping.GetTableMapping<T>();

            foreach (IColumnMapping colMapping in tableMapping.ColumnMappings)
            {
                int i = reader.GetOrdinal(colMapping.SourceColumn);
                if (i < 0)
                    continue;

                object val = GetValue(reader, i);
                if (val == DBNull.Value || val == null)
                    continue;
                string fieldName = colMapping.DataSetColumn;
                PropertyInfo property = type.GetProperty(fieldName);
                if (property != null)
                {
                    if (property.PropertyType.IsEnum)
                    {
                        val = Enum.ToObject(property.PropertyType, val); ;
                    }
                    else if (Type.GetTypeCode(property.PropertyType) == TypeCode.Object)
                    {
                        if (val is string)
                        {
                            var str = val.ToString();
                            val = string.IsNullOrEmpty(str) ? string.Empty : str.ToJsonObject(property.PropertyType);
                        }
                    }
                    property.SetValue(entity, val);
                }
            }
            return entity;
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="reader"></param>
        /// <returns></returns>
        protected internal virtual IDictionary<string, object> LoadDataReader(DbDataReader reader)
        {
            IDictionary<string, object> row = new Dictionary<string, object>(StringComparer.OrdinalIgnoreCase);
            for (int i = 0; i < reader.FieldCount; i++)
            {
                string fieldName = reader.GetName(i);
                object val;
                if (!reader.IsDBNull(i))
                    val = reader.GetValue(i);
                else
                    val = null;

                row.Add(fieldName, val);
            }
            return row;
        }
        #endregion

        #endregion

        #region 填充数据表

        /// <summary>
        /// 
        /// </summary>
        /// <param name="dataTable"></param>
        /// <param name="sqlCommandTxt"></param>
        /// <param name="parameters"></param>
        /// <returns></returns>
        public int FillDataTable(DataTable dataTable, string sqlCommandTxt, params DbParameter[] parameters)
        {
            return FillDataTable(dataTable, sqlCommandTxt, CommandType.Text, parameters);
        }
        /// <summary>
        /// 根据指定的sql语句填充数据表
        /// </summary>
        /// <param name="dataTable"></param>
        /// <param name="sqlCommandTxt"></param>
        /// <param name="cmdType"></param>
        /// <param name="parameters"></param>
        /// <returns></returns>
        public int FillDataTable(DataTable dataTable, string sqlCommandTxt, CommandType cmdType, params DbParameter[] parameters)
        {
            return FillDataTable(dataTable, sqlCommandTxt, cmdType, 0, parameters);
        }

        /// <summary>
        /// 根据指定的sql语句填充数据表
        /// </summary>
        /// <param name="dataTable"></param>
        /// <param name="sqlCommandTxt"></param>
        /// <param name="cmdType"></param>
        /// <param name="maxRowCount"></param>
        /// <param name="parameters"></param>
        /// <returns></returns>
        public virtual int FillDataTable(DataTable dataTable, string sqlCommandTxt, CommandType cmdType, int maxRowCount, params DbParameter[] parameters)
        {
            using (DbCommand command = CreateCommand(sqlCommandTxt, cmdType, parameters))
            {
                try
                {
                    return FillDataTable(dataTable, command, maxRowCount);
                }
                finally
                {
                    command.Connection.Close();
                    command.Connection.Dispose();
                }
            }
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="dataTable"></param>
        /// <param name="command"></param>
        /// <param name="maxRowCount"></param>
        /// <returns></returns>
        protected internal virtual int FillDataTable(DataTable dataTable, DbCommand command, int maxRowCount)
        {
            int count = 0;
            try
            {
                using (DbDataAdapter adapter = CreateDataAdapter(command))
                {
                    if (maxRowCount > 0)
                    {
                        count = adapter.Fill(0, maxRowCount, dataTable);
                    }
                    else
                    {
                        count = adapter.Fill(dataTable);
                    }
                }
            }
            catch (Exception e)
            {
                OnExceptionEventRaise(ConnectionString, command.CommandText, e);
            }
            return count;
        }
        #endregion

        #region 填充数据集

        /// <summary>
        /// 
        /// </summary>
        /// <param name="dataSet"></param>
        /// <param name="sqlCommandTxt"></param>
        /// <param name="parameters"></param>
        /// <returns></returns>
        public int FillDataSet(DataSet dataSet, string sqlCommandTxt, DbParameter[] parameters)
        {
            return FillDataSet(dataSet, sqlCommandTxt, CommandType.Text, parameters);
        }
        /// <summary>
        /// 通过执行sql语句填充一个数据表
        /// </summary>
        /// <param name="dataSet">要执行的SQL语句</param>
        /// <param name="sqlCommandTxt">要执行的SQL语句</param>
        /// <param name="cmdType">命令解析类型</param>
        /// <param name="parameters">参数对象</param>
        /// <returns>已经填充的记录数</returns>
        public virtual int FillDataSet(DataSet dataSet, string sqlCommandTxt, CommandType cmdType, params DbParameter[] parameters)
        {
            using (DbCommand command = CreateCommand(sqlCommandTxt, cmdType, parameters))
            {
                try
                {
                    return FillDataSet(dataSet, command);
                }
                finally
                {
                    command.Connection.Close();
                    command.Connection.Dispose();
                }
            }
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="dataSet"></param>
        /// <param name="command"></param>
        /// <returns></returns>
        protected internal virtual int FillDataSet(DataSet dataSet, DbCommand command)
        {
            int count = 0;
            try
            {
                using (DbDataAdapter adapter = CreateDataAdapter(command))
                {
                    count = adapter.Fill(dataSet);
                }
            }
            catch (Exception e)
            {
                OnExceptionEventRaise(ConnectionString, command.CommandText, e);
            }
            return count;
        }
        #endregion

        #region 执行事务

        ///// <summary>
        ///// 
        ///// </summary>
        ///// <param name="cmdList"></param>
        ///// <returns></returns>
        //public bool ExecuteTransaction(IEnumerable<ITransactionCommand> cmdList)
        //{
        //    bool success = false;
        //    DbConnection con = CreateConnection();
        //    if (GetConnectionState(con) == ConnectionState.Closed)
        //        con.Open();
        //    using (DbTransaction tran = con.BeginTransaction())
        //    {
        //        try
        //        {
        //            foreach (ITransactionCommand tc in cmdList)
        //            {
        //                using (DbCommand com = con.CreateCommand())
        //                {
        //                    try
        //                    {
        //                        //if (tc.ActionBeforeExecution != null)
        //                        //    tc.ActionBeforeExecution(tc, EventArgs.Empty);
        //                        com.CommandTimeout = this.ExecuteTimeout;
        //                        com.Transaction = tran;
        //                        com.CommandText = tc.ExecuteSql;
        //                        com.CommandType = tc.CmdType;
        //                        if (tc.Parameters != null)
        //                            com.Parameters.AddRange(tc.Parameters);
        //                        com.ExecuteNonQuery();

        //                        //if (tc.ActionAfterExecution != null)
        //                        //    tc.ActionAfterExecution(tc, EventArgs.Empty);
        //                    }
        //                    catch (DbException e)
        //                    {
        //                        this.OnExceptionEventRaise(this._connectionString, com.CommandText, e);
        //                        com.Dispose();
        //                        throw e;
        //                    }
        //                }
        //            }

        //            tran.Commit();
        //            success = true;
        //        }
        //        catch
        //        {
        //            tran.Rollback();
        //        }
        //        finally
        //        {
        //            tran.Dispose();
        //            con.Close();
        //            con.Dispose();
        //        }
        //    }
        //    return success;
        //}
        #endregion

        /// <summary>
        /// 引发异常事件
        /// </summary>
        /// <param name="connectionString"></param>
        /// <param name="sqlCommandTxt"></param>
        /// <param name="exception"></param>
        protected void OnExceptionEventRaise(string connectionString, string sqlCommandTxt, Exception exception)
        {
            OnExceptionEventRaise(connectionString, sqlCommandTxt, exception, RaiseException);
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="connectionString"></param>
        /// <param name="sqlCommandTxt"></param>
        /// <param name="exception"></param>
        /// <param name="raiseException"></param>
        protected virtual void OnExceptionEventRaise(string connectionString, string sqlCommandTxt, Exception exception, bool raiseException)
        {
            DbExceptionEventArgs e = new DbExceptionEventArgs(connectionString, sqlCommandTxt, exception);

            if (_exceptionEventHandler != null)
                _exceptionEventHandler(this, e);
            if (exception is DbException)
                WriteErrorLog(exception.Message, exception);
            else
                WriteFatalLog(exception);
            if (e.ThrowException ?? raiseException)
                throw exception;
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="name"></param>
        /// <param name="cmdText"></param>
        /// <param name="cmdType"></param>
        /// <returns></returns>
        public abstract IDataCommand CreateDataCommand(string name, string cmdText, CommandType cmdType);
        /// <summary>
        /// 
        /// </summary>
        /// <typeparam name="TEntity"></typeparam>
        /// <returns></returns>
        public abstract IDataOperation<TEntity> CreateDataOperation<TEntity>() where TEntity : class;
        /// <summary>
        /// 
        /// </summary>
        /// <typeparam name="TEntity"></typeparam>
        /// <returns></returns>
        public abstract IDataQuery<TEntity> CreateDataQuery<TEntity>() where TEntity : class;
        /// <summary>
        /// 
        /// </summary>
        /// <typeparam name="TEntity"></typeparam>
        /// <returns></returns>
        public virtual IObjectQuery<TEntity> CreateObjectQuery<TEntity>() where TEntity : class
        {
            return new NativeObjectQuery<TEntity>(this);
        }

    }

    /// <summary>
    /// 表示访问数据库时引发异常事件
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    public delegate void DbExceptionEventHandler(object sender, DbExceptionEventArgs e);

    /// <summary>
    /// 访问数据库时引发异常事件的参数
    /// </summary>
    public class DbExceptionEventArgs : EventArgs
    {
        Exception _exception;
        string _database;
        string _sqlstr;
        /// <summary>
        /// 
        /// </summary>
        /// <param name="dbName"></param>
        /// <param name="sqlstr"></param>
        /// <param name="exception"></param>
        public DbExceptionEventArgs(string dbName, string sqlstr, Exception exception)
        {
            _exception = exception;
            _database = dbName;
            _sqlstr = sqlstr;
        }
        /// <summary>
        /// 当前使用的数据库
        /// </summary>
        public string CurrentDataBase
        {
            get
            {
                return _database;
            }
        }
        /// <summary>
        /// 正在执行的sql语句
        /// </summary>
        public string ExecutingSql
        {
            get
            {
                return _sqlstr;
            }
        }
        /// <summary>
        /// 异常对象
        /// </summary>
        public Exception Exception
        {
            get
            {
                return _exception;
            }
        }
        /// <summary>
        /// 
        /// </summary>
        public bool? ThrowException
        {
            get; set;
        }
    }
}
